package com.duojuhe.coremodule.form.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.duojuhe.common.annotation.KeyLock;
import com.duojuhe.common.bean.UserTokenInfoVo;
import com.duojuhe.common.enums.SystemEnum;
import com.duojuhe.common.utils.dateutils.DateUtils;
import com.duojuhe.common.utils.idgenerator.UUIDUtils;
import com.duojuhe.common.utils.iputil.IPUtils;
import com.duojuhe.common.utils.jsonutils.JsonUtils;
import com.duojuhe.coremodule.form.entity.FormProjectResult;
import com.duojuhe.coremodule.form.entity.FormProjectSetting;
import com.duojuhe.coremodule.form.enums.FormEnum;
import com.duojuhe.common.result.ErrorCodes;
import com.duojuhe.common.result.PageResult;
import com.duojuhe.common.result.ServiceResult;
import com.duojuhe.common.utils.page.PageHelperUtil;
import com.duojuhe.coremodule.BaseService;
import com.duojuhe.coremodule.form.entity.FormProject;
import com.duojuhe.coremodule.form.mapper.*;
import com.duojuhe.coremodule.form.pojo.project.FormProjectIdReq;
import com.duojuhe.coremodule.form.pojo.project.QueryFormProjectDetailsRes;
import com.duojuhe.coremodule.form.pojo.project.QueryFormProjectRes;
import com.duojuhe.coremodule.form.pojo.projectitem.QueryFormProjectItemRes;
import com.duojuhe.coremodule.form.pojo.projectitem.QueryFormProjectItemTableHeadRes;
import com.duojuhe.coremodule.form.pojo.projectlogic.FormProjectLogicCondition;
import com.duojuhe.coremodule.form.pojo.projectlogic.QueryFormProjectLogicPageRes;
import com.duojuhe.coremodule.form.pojo.projectresult.QueryFormProjectResultPageRes;
import com.duojuhe.coremodule.form.pojo.projectresult.QueryPublicFormProjectResultPageReq;
import com.duojuhe.coremodule.form.pojo.projectresult.SaveFormProjectResultReq;
import com.duojuhe.coremodule.form.pojo.projectsetting.QueryFormProjectSettingRes;
import com.duojuhe.coremodule.form.pojo.projectsetting.QueryPublicFormProjectSettingRes;
import com.duojuhe.coremodule.form.pojo.projectstyle.QueryFormProjectStyleRes;
import com.duojuhe.coremodule.form.service.FormProjectPublicService;
import com.duojuhe.coremodule.form.utils.handle.HandleFormUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Slf4j
@Service
public class FormProjectPublicServiceImpl extends BaseService implements FormProjectPublicService {
    @Resource
    private FormProjectMapper formProjectMapper;
    @Resource
    private FormProjectSettingMapper formProjectSettingMapper;
    @Resource
    private FormProjectStyleMapper formProjectStyleMapper;
    @Resource
    private FormProjectItemMapper formProjectItemMapper;
    @Resource
    private FormProjectLogicMapper formProjectLogicMapper;
    @Resource
    private FormProjectResultMapper formProjectResultMapper;

    /**
     * 公开保存表单结果值
     * @param req
     * @return
     */
    @KeyLock(lockKeyParts = "projectId")
    @Override
    public ServiceResult<String> savePublicFormProjectResult(SaveFormProjectResultReq req) {
        //问卷类型
        String projectType = FormEnum.FormProjectType.FORM_SURVEY_QUESTIONNAIRE.getKey();
        //项目id
        String projectId = req.getProjectId();
        QueryFormProjectRes formProject = formProjectMapper.queryFormProjectResByProjectId(projectId);
        if (formProject == null || !projectType.equals(formProject.getProjectTypeCode())) {
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //项目必须是发布了的
        String published = FormEnum.FormProjectStatus.FORM_PROJECT_PUBLISHED.getKey();
        if (!published.equals(formProject.getStatusCode())){
            return ServiceResult.fail(ErrorCodes.FORM_PROJECT_NO_PUBLISHED);
        }
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //检查配置
        FormProjectSetting formProjectSetting = formProjectSettingMapper.selectByPrimaryKey(projectId);
        if (formProjectSetting == null) {
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        String errorStr = checkFormProjectSetting(formProjectSetting,userTokenInfoVo);
        if (StringUtils.isNotBlank(errorStr)){
            return ServiceResult.fail(errorStr);
        }
        //检查风格
        QueryFormProjectStyleRes styleRes = formProjectStyleMapper.queryFormProjectStyleResByProjectId(projectId);
        if (styleRes == null) {
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //构建流程当前逻辑
        List<QueryFormProjectLogicPageRes> logicResList = formProjectLogicMapper.queryFormProjectLogicPageResByProjectId(req.getProjectId());
        String formLogicConfig = HandleFormUtils.getFormLogicConfigJsonString(logicResList);
        //项目明细集合
        PageHelperUtil.defaultOrderBy("sort asc,updateTime desc, projectId desc");
        List<QueryFormProjectItemRes> itemResList = formProjectItemMapper.queryFormProjectItemResListByProjectId(projectId);
        PageHelperUtil.clearPage();
        if (itemResList.isEmpty()){
            return ServiceResult.fail(ErrorCodes.FORM_PROJECT_NO_FORM_ITEM);
        }
        for (QueryFormProjectItemRes res:itemResList){
            HandleFormUtils.setHandleFormProjectItemRes(res);
        }
        //构建对象
        QueryFormProjectDetailsRes detailsRes = new QueryFormProjectDetailsRes();
        //项目详情
        detailsRes.setFormProjectRes(formProject);
        //项目风格详情
        detailsRes.setFormProjectStyleRes(styleRes);
        //项目明细
        detailsRes.setFormProjectItemResList(itemResList);
        String formContentConfig = JSON.toJSONString(detailsRes);

        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        //获取ip当前客户
        String submitIp = IPUtils.getClientIP(request);
        //当前时间
        Date nowDate = new Date();

        //当前登录人id
        String userId = userTokenInfoVo.getUserId();
        //提交流水号
        String serialNumber = UUIDUtils.getSequenceNo();
        //结果对象
        FormProjectResult projectResult = new FormProjectResult();
        projectResult.setId(UUIDUtils.getUUID32());
        projectResult.setSerialNumber(serialNumber);
        projectResult.setCreateTime(nowDate);
        projectResult.setUpdateTime(nowDate);
        projectResult.setCreateUserId(userId);
        projectResult.setUpdateUserId(userId);
        projectResult.setSubmitUserId(userId);
        projectResult.setCreateDeptId(userTokenInfoVo.getCreateDeptId());
        projectResult.setTenantId(userTokenInfoVo.getTenantId());
        projectResult.setProjectId(projectId);
        projectResult.setProjectKey(formProject.getProjectKey());
        projectResult.setOriginalData(JsonUtils.objToJson(req.getOriginalData()));
        projectResult.setProcessData(JsonUtils.objToJson(req.getProcessData()));
        projectResult.setSubmitIp(submitIp);
        projectResult.setSubmitOs(req.getSubmitOs());
        projectResult.setSubmitBrowser(req.getSubmitBrowser());
        projectResult.setSubmitUa(JsonUtils.objToJson(req.getSubmitUa()));
        projectResult.setCompleteTime(req.getCompleteTime());
        projectResult.setFormLogicConfig(formLogicConfig);
        projectResult.setFormContentConfig(formContentConfig);
        projectResult.setSubmitSource(userTokenInfoVo.getUserLoginSource());
        formProjectResultMapper.insertSelective(projectResult);
        return ServiceResult.ok(serialNumber);
    }


    /**
     * 根据项目id查询详情
     * @param req
     * @return
     */
    @Override
    public ServiceResult<QueryFormProjectRes> queryPublicFormProjectResByProjectId(FormProjectIdReq req) {
        //项目id
        String projectId = req.getProjectId();
        QueryFormProjectRes res = formProjectMapper.queryFormProjectResByProjectId(projectId);
        if (res == null) {
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        return ServiceResult.ok(res);
    }

    /**
     * 根据项目id查询项目明细
     * @param req
     * @return
     */
    @Override
    public ServiceResult<QueryFormProjectDetailsRes> queryPublicFormProjectDetailsResByProjectId(FormProjectIdReq req) {
        //项目id
        String projectId = req.getProjectId();
        QueryFormProjectRes projectRes = formProjectMapper.queryFormProjectResByProjectId(projectId);
        if (projectRes == null) {
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        QueryFormProjectStyleRes styleRes = formProjectStyleMapper.queryFormProjectStyleResByProjectId(projectId);
        if (styleRes == null) {
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        QueryFormProjectDetailsRes detailsRes = new QueryFormProjectDetailsRes();
        //项目详情
        detailsRes.setFormProjectRes(projectRes);
        //项目风格详情
        detailsRes.setFormProjectStyleRes(styleRes);
        //项目明细集合
        PageHelperUtil.defaultOrderBy("sort asc,updateTime desc, projectId desc");
        List<QueryFormProjectItemRes> itemResList = formProjectItemMapper.queryFormProjectItemResListByProjectId(projectId);
        for (QueryFormProjectItemRes res:itemResList){
            HandleFormUtils.setHandleFormProjectItemRes(res);
        }
        detailsRes.setFormProjectItemResList(itemResList);
        return ServiceResult.ok(detailsRes);
    }

    /**
     * 【项目设置详情】根据项目ID查询项目设置详情
     * @param req
     * @return
     */
    @KeyLock(lockKeyParts = "projectId")
    @Override
    public ServiceResult<QueryPublicFormProjectSettingRes> queryPublicFormProjectSettingResByProjectId(FormProjectIdReq req) {
        QueryPublicFormProjectSettingRes res = new QueryPublicFormProjectSettingRes();
        res.setWriteShowStatus(SystemEnum.YES_NO.NO.getKey());
        res.setWriteShowMessage(ErrorCodes.PARAM_ERROR.getMessage());
        res.setFormProjectRes(new QueryFormProjectRes());
        try {
            //项目id
            String projectId = req.getProjectId();
            QueryFormProjectRes projectRes = formProjectMapper.queryFormProjectResByProjectId(projectId);
            if (projectRes == null) {
                return ServiceResult.ok(res);
            }
            //问卷类型
            String projectType = FormEnum.FormProjectType.FORM_SURVEY_QUESTIONNAIRE.getKey();
            if (!projectType.equals(projectRes.getProjectTypeCode())) {
                return ServiceResult.ok(res);
            }
            //项目没有发布提示参数错误
            String unpublished = FormEnum.FormProjectStatus.FORM_PROJECT_UNPUBLISHED.getKey();
            if (unpublished.equals(projectRes.getStatusCode())){
                return ServiceResult.ok(res);
            }

            //检查配置
            FormProjectSetting formProjectSetting = formProjectSettingMapper.selectByPrimaryKey(projectId);
            if (formProjectSetting == null) {
                return ServiceResult.ok(res);
            }
            //当前登录人
            UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
            //检查
            String errorStr = checkFormProjectSetting(formProjectSetting,userTokenInfoVo);
            if (StringUtils.isNotBlank(errorStr)){
                res.setWriteShowMessage(errorStr);
                return ServiceResult.ok(res);
            }
            //项目结束了提示项目结束
            String stop = FormEnum.FormProjectStatus.FORM_PROJECT_STOP.getKey();
            if (stop.equals(projectRes.getStatusCode())){
                res.setWriteShowMessage(FormEnum.FormProjectStatus.FORM_PROJECT_STOP.getValue());
                return ServiceResult.ok(res);
            }
            //更新项目表
            FormProject updateFormProject = new FormProject();
            updateFormProject.setProjectId(projectId);
            updateFormProject.setHits(projectRes.getHits()+1);
            formProjectMapper.updateByPrimaryKeySelective(updateFormProject);
            //构建返回值
            res.setFormProjectSettingRes(new QueryFormProjectSettingRes(formProjectSetting));
            res.setWriteShowStatus(SystemEnum.YES_NO.YES.getKey());
            res.setFormProjectRes(projectRes);
            res.setWriteShowMessage(ErrorCodes.SUCCESS.getMessage());
            return ServiceResult.ok(res);
        }catch (Exception e){
            res.setWriteShowMessage(ErrorCodes.FAIL.getMessage());
            return ServiceResult.ok(res);
        }
    }
    /**
     * 根据项目id查询表单项目逻辑集合
     * @param req
     * @return
     */
    @KeyLock(lockKeyParts = "projectId")
    @Override
    public ServiceResult<List<QueryFormProjectLogicPageRes>> queryPublicFormProjectLogicPageResByProjectId(FormProjectIdReq req) {
        PageHelperUtil.defaultOrderBy("createTime asc, id desc");
        List<QueryFormProjectLogicPageRes> logicPageResList = formProjectLogicMapper.queryFormProjectLogicPageResByProjectId(req.getProjectId());
        for (QueryFormProjectLogicPageRes res:logicPageResList){
            if (StringUtils.isNotBlank(res.getConditionJson())){
                res.setConditionList(JSONObject.parseArray(res.getConditionJson(), FormProjectLogicCondition.class));
            }
        }
        return ServiceResult.ok(logicPageResList);
    }

    /**
     * 根据项目Id查询表单项目的表头信息
     * @param req
     * @return
     */
    @Override
    public ServiceResult<List<QueryFormProjectItemTableHeadRes>> queryPublicFormProjectItemTableHeadResByProjectId(FormProjectIdReq req) {
        PageHelperUtil.defaultOrderBy("sort asc,updateTime desc, itemId desc");
        List<QueryFormProjectItemTableHeadRes> list = formProjectItemMapper.queryFormProjectItemTableHeadResByProjectId(req.getProjectId());
        for (QueryFormProjectItemTableHeadRes res:list){
            HandleFormUtils.setHandleFormProjectItemPageRes(res);
        }

        return ServiceResult.ok(list);
    }

    /**
     * 【分页查询】根据条件查询表单项目提交结果集合
     * @param req
     * @return
     */
    @Override
    public ServiceResult<PageResult<List<QueryFormProjectResultPageRes>>> queryPublicFormProjectResultPageResList(QueryPublicFormProjectResultPageReq req) {
        //检查配置
        FormProjectSetting formProjectSetting = formProjectSettingMapper.selectByPrimaryKey(req.getProjectId());
        if (formProjectSetting == null || !SystemEnum.IS_YES.YES.getKey().equals(formProjectSetting.getResultPublic())) {
            return PageHelperUtil.returnServiceResult(req, new ArrayList<>());
        }
        PageHelperUtil.orderByAndStartPage(req, "updateTime desc, id desc");
        List<QueryFormProjectResultPageRes> list = formProjectResultMapper.queryPublicFormProjectResultPageResList(req);
        for (QueryFormProjectResultPageRes res:list){
            //填写结果处理后的数据
            if (StringUtils.isNotBlank(res.getProcessData())){
                res.setProcessDataMap(JSONObject.parseObject(res.getProcessData(), Map.class));
            }
            //提交用户客户端信息
            if (StringUtils.isNotBlank(res.getSubmitUa())){
                res.setSubmitUaMap(JSONObject.parseObject(res.getSubmitUa(), Map.class));
            }
        }
        return PageHelperUtil.returnServiceResult(req, list);
    }


    /**
     * 检查配置
     * @param formProjectSetting
     * @param userTokenInfoVo
     */
    private String checkFormProjectSetting(FormProjectSetting formProjectSetting,UserTokenInfoVo userTokenInfoVo){
        //项目id
        String projectId = formProjectSetting.getProjectId();
        //当前时间
        Date nowDate = new Date();
        //是
        Integer YES = SystemEnum.IS_YES.YES.getKey();
        //是否定时收集
        Integer showTimedCollection = formProjectSetting.getShowTimedCollection();
        if (YES.equals(showTimedCollection)){
            //定时收集开始时间
            Date timedCollectionBeginTime = formProjectSetting.getTimedCollectionBeginTime();
            if (timedCollectionBeginTime!=null&&timedCollectionBeginTime.getTime()>nowDate.getTime()){
                //定时未开始提示文字
                String timedNotEnabledPromptText = formProjectSetting.getTimedNotEnabledPromptText();
                return StringUtils.isBlank(timedNotEnabledPromptText)?"未开始!":timedNotEnabledPromptText;
            }
            //定时收集结束时间
            Date timedCollectionEndTime = formProjectSetting.getTimedCollectionEndTime();
            if (timedCollectionEndTime!=null&&timedCollectionEndTime.getTime()<nowDate.getTime()){
                //定时结束提示文字
                String timedDeactivatePromptText = formProjectSetting.getTimedDeactivatePromptText();
                return StringUtils.isBlank(timedDeactivatePromptText)?"已结束!":timedDeactivatePromptText;
            }
        }
        //是否限制填写次数
        Integer limitWrite = formProjectSetting.getLimitWrite();
        //是否显示定量收集
        Integer showQuantitative = formProjectSetting.getShowQuantitative();
        if (YES.equals(showQuantitative) || YES.equals(limitWrite)){
            List<FormProjectResult> projectResultList = formProjectResultMapper.queryFormProjectResultListByProjectId(projectId);
            if (YES.equals(showQuantitative)){
                //总收集数量
                Integer quantitativeTotalQuantity = formProjectSetting.getQuantitativeTotalQuantity();
                //定量收集完成提示文字
                String quantitativeEndPromptText = formProjectSetting.getQuantitativeEndPromptText();
                if (projectResultList.size()>=quantitativeTotalQuantity){
                    return StringUtils.isBlank(quantitativeEndPromptText)?"已经达到总收集数量,停止收集!":quantitativeEndPromptText;
                }
            }
            if (YES.equals(limitWrite)){
                //每人限填次数
                Integer everyoneWriteNum = formProjectSetting.getEveryoneWriteNum();
                //限制填写次数方式，1=总共,2=每天
                String limitWriteNumMode = formProjectSetting.getLimitWriteNumMode();
                //用户过滤数据id
                String filterId = userTokenInfoVo.getUserId();
                if ("1".equals(limitWriteNumMode)){
                    //总数量
                    long totalSize = projectResultList.stream().filter(e->filterId.equals(e.getCreateUserId())).count();
                    if (totalSize>=everyoneWriteNum){
                        return "您允许提交次数已用完,总共允许"+everyoneWriteNum+"次";
                    }
                }else {
                    //今天总数量
                    long totalSize = projectResultList.stream().filter(e->filterId.equals(e.getCreateUserId())&& DateUtils.isToday(e.getCreateTime())).count();
                    if (totalSize>=everyoneWriteNum){
                        return "您今日允许提交次数已用完,允许"+everyoneWriteNum+"次";
                    }
                }
            }
        }
        return StringUtils.EMPTY;
    }

}
